/**********************************************************
 * HD44780 Library
 * (c) Maksym Shevchenko <maksym.shevchenko@r0land.kiev.ua
 **********************************************************/
#include <xc.h>
#include "lcd.h"
#include "system.h"

char lcd_cur_pos = 0;
char lcd_cur_line = 0;

void lcd_busy_wait()
{
    unsigned char status = 0;
    LCD_DATA_tris = 0xFF; 
    LCD_RS_pin = 0;
    LCD_RW_pin = 1;  
    do
    {
        LCD_E_pin  = 0;                   
        __delay_us(1);
        LCD_E_pin  = 1;                  
        __delay_us(1);
        status = LCD_DATA_pins;
        LCD_E_pin  = 0;       
    } 
    while (status&0x80); 
    LCD_RW_pin = 0; 
    LCD_RS_pin = 0; 
    LCD_DATA_tris = 0x00; 
} 

void lcd_write(unsigned char data, unsigned char RSbit)
{
    di();
    LCD_RS_pin = RSbit; 
    LCD_RW_pin = 0;    
    LCD_E_pin = 0;

    LCD_DATA_tris = 0x00; 
    LCD_DATA_pins = data;

    __delay_us(1);
    LCD_E_pin = 1;
    __delay_us(2);
    LCD_E_pin = 0;

    lcd_busy_wait(); 
    ei();
}

void lcd_init()
{
    lcd_busy_wait();
    di();
    LCD_RS_tris = 0;
    LCD_RW_tris = 0;
    LCD_E_tris  = 0;
    LCD_DATA_tris = 0x00;
    LCD_RS_pin = 0;
    LCD_RW_pin = 0;
    LCD_E_pin  = 1;
    LCD_DATA_pins = 0x00;
    __delay_us(2);
    ei();
    lcd_busy_wait();

    lcd_write(LCD_CMD_CLS, lcd_cmd); 
    lcd_write(LCD_CMD_SETFUNCTION, lcd_cmd); 
    lcd_write(LCD_CMD_SHIFT, lcd_cmd);      
    lcd_write(LCD_CMD_SETMODE, lcd_cmd);   
    lcd_write(LCD_CMD_SETDISPLAY, lcd_cmd); 
}

// ������ ������������� �������
// *arrayptr - ��������� �� ������ � �������
// 64 / 8 = 8 ��������
// offset - �������� ������������ ���������� ������ - 0,8, ...
// lcd_writechr(simvol1, 0); // Offset 0 - 40h-47h in CGRAM.
void lcd_writechr(unsigned char *arrayptr, int offset)
{
    unsigned char i;

    lcd_write(LCD_CMD_SETCGADDR + offset, lcd_cmd); // Set the CGRAM address.

    for (i=0; i<8; ++i)
    {
        lcd_write(*arrayptr++, lcd_data);
    }
};

void lcd_home10()
{
    lcd_write(lcd_line10, lcd_cmd);
    lcd_cur_line=0;
    lcd_cur_pos =0;
};

void lcd_home20()
{
    lcd_write(lcd_line20, lcd_cmd);
    lcd_cur_line=1;
    lcd_cur_pos =0;
};

void lcd_cls()
{
    lcd_write(LCD_CMD_CLS, lcd_cmd); 
    lcd_home10();
};

void lcd_gotoXY(char _x, char _y)
{
    lcd_cur_pos = _x%16;
    lcd_cur_line = _y%2;

    if (!(LCD_CMD_SETFUNCTION & 0b00010000))
        _y = 0;
}

void putch(char _data)
{
    if (lcd_cur_pos == 0 && lcd_cur_line ==0)
    {
       lcd_cls();
    }
    else
    {
        if (lcd_cur_pos == 16)
        {
            lcd_cur_pos = 0;
            if (LCD_CMD_SETFUNCTION & 0b00010000)
            {
                if (lcd_cur_line == 0)
                {
                    lcd_cur_line = 1;
                }
                else
                {
                    lcd_cur_line = 0;
                    lcd_cls();
                }
            }
            else
                lcd_cls();
        };
    }

    if (lcd_cur_line == 0)
        lcd_write(lcd_line10+lcd_cur_pos, lcd_cmd);
    if (lcd_cur_line == 1)
        lcd_write(lcd_line20+lcd_cur_pos, lcd_cmd);
    lcd_write(_data, lcd_data);
    lcd_cur_pos++;
};

